#include "SharedData.h"

SharedData *shared_data_sys_ = nullptr;
int64 *sys_timestamps_;
int64 last_time_ {0};

constexpr int one_ms_ = 1000;
int one_second_ {0};
int64 one_jitter_sum_ {0};

// 计时器回调函数
KSError __stdcall TimerCallBack(void * /*pArgs*/, void * /*pContext*/);

extern "C" KSError __declspec(dllexport) __stdcall InitFunction(void *pArgs, void * /*pContext*/)
{
    shared_data_sys_ = static_cast<SharedData *>(pArgs);

    //------------------------------------------------------------------------------------------------------------
    // 现在创建事件。稍后我们将在用户空间等待此事件。
    // 该事件将由 timer 函数设置。
    //------------------------------------------------------------------------------------------------------------
    KSError error = KS_createEvent(&shared_data_sys_->finished_event_handle, "JitterMeasureEvent", KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    //------------------------------------------------------------------------------------------------------------
    // 现在创建回调。每次计时器周期到期时，都会调用此函数。
    //------------------------------------------------------------------------------------------------------------
    error = KS_createCallBack(&shared_data_sys_->timer_call_back_handle, TimerCallBack, nullptr, KSF_DIRECT_EXEC, 0);
    if (error != KS_OK) { return error; }

    //------------------------------------------------------------------------------------------------------------
    // 创建 1 kHz 的计时器。触发的对象是 'timer_call_back_handle' 参数。
    // 请注意，最小计时器周期为 1 微秒。
    //------------------------------------------------------------------------------------------------------------
    error = KS_createTimer(&shared_data_sys_->timer_handle, 1 * ms_, shared_data_sys_->timer_call_back_handle, KSF_REALTIME_EXEC | KSF_DONT_START);
    if (error != KS_OK) { return error; }

    return KS_OK;
}

//--------------------------------------------------------------------------------------------------------------
// 这是删除计时器、存储的回调和信令事件的清理函数。
//--------------------------------------------------------------------------------------------------------------
extern "C" KSError __declspec(dllexport) __stdcall ExitFunction(void * /*pArgs*/, void * /*pContext*/)
{
    if (shared_data_sys_ == nullptr) { return KSERROR_FUNCTION_NOT_AVAILABLE; }

    //------------------------------------------------------------------------------------------------------------
    // 使用计时器手柄删除计时器。
    // 请注意，计时器可能仍在运行。删除前无需停止它。
    //------------------------------------------------------------------------------------------------------------
    KSError error = KS_removeTimer(shared_data_sys_->timer_handle);
    if (error != KS_OK) return error;

    //------------------------------------------------------------------------------------------------------------
    // 使用回调句柄删除回调对象。
    //------------------------------------------------------------------------------------------------------------
    error = KS_removeCallBack(shared_data_sys_->timer_call_back_handle);
    if (error != KS_OK) return error;

    //------------------------------------------------------------------------------------------------------------
    // 使用事件句柄删除事件对象。
    //------------------------------------------------------------------------------------------------------------
    error = KS_closeEvent(shared_data_sys_->finished_event_handle);
    if (error != KS_OK) return error;

    return KS_OK;
}

//--------------------------------------------------------------------------------------------------------------
// 这是回调函数。每次向 timer 发出信号时，都会调用
//--------------------------------------------------------------------------------------------------------------
KSError __stdcall TimerCallBack(void * /*pArgs*/, void * /*pContext*/)
{
    //------------------------------------------------------------------------------------------------------------
    // 从 TSC 获取 64 位 clock 值以确定我们何时被调用。
    //------------------------------------------------------------------------------------------------------------
    int64 time;
    if (const KSError error = KS_getClock(&time, KS_CLOCK_MEASURE_HIGHEST); error != KS_OK) { return error; }

    //------------------------------------------------------------------------------------------------------------
    // 如果我们仍处于预测量期：不要递增 shared_data_sys_->index 并返回。
    //------------------------------------------------------------------------------------------------------------
    if (shared_data_sys_->pre_measure_count > 0) {
        --shared_data_sys_->pre_measure_count;
        last_time_ = time;
        return KS_OK;
    }

    //-------------------------------------------------------------------------
    // 计算抖动
    //-------------------------------------------------------------------------
    int64 jitter_time = time - last_time_;
    int64 single_timestamp = jitter_time;
    KS_convertClock(&single_timestamp, KS_CLOCK_MEASURE_HIGHEST, KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);
    jitter_time = single_timestamp;

    // 定时1 ms 抖动时间
    jitter_time = 1 * ms_ - jitter_time;
    if (const int class_index = static_cast<int>(KSRTL_fabs(static_cast<double>(jitter_time) / us_)); class_index < 9) { shared_data_sys_->classes[class_index]++; }
    else { shared_data_sys_->classes[9]++; }

    // 更新最大值和最小值
    if (shared_data_sys_->measure_value.max_value < jitter_time) { shared_data_sys_->measure_value.max_value = jitter_time; }

    if (shared_data_sys_->measure_value.min_value > jitter_time) { shared_data_sys_->measure_value.min_value = jitter_time; }

    // 1s内的最大值和最小值
    if (one_second_ < one_ms_) {
        if (shared_data_sys_->measure_value.lat_max < jitter_time) { shared_data_sys_->measure_value.lat_max = jitter_time; }
        if (shared_data_sys_->measure_value.lat_min > jitter_time) { shared_data_sys_->measure_value.lat_min = jitter_time; }

        one_jitter_sum_ += jitter_time;
        one_second_++;
        if (one_second_ == one_ms_) { shared_data_sys_->measure_value.lat_avg = one_jitter_sum_ / one_ms_; }
    }
    else {
        one_second_ = 0;
        one_jitter_sum_ = 0;

        shared_data_sys_->measure_value.lat_min = 0;
        shared_data_sys_->measure_value.lat_max = 0;
    }

    shared_data_sys_->measure_value.current_value = jitter_time;
    last_time_ = time;

    //------------------------------------------------------------------------------------------------------------
    // 如果我们存储了所有想要的时间戳，则在 userspace 中设置 event 以通知应用程序并退出。
    //------------------------------------------------------------------------------------------------------------
    if (++shared_data_sys_->index == shared_data_sys_->items) {
        shared_data_sys_->measure_value.current_time = shared_data_sys_->items;
        shared_data_sys_->finish_flag = 1;
        return KSERROR_OPERATION_ABORTED;
    }

    if (shared_data_sys_->finish_flag == 1) { return KSERROR_OPERATION_ABORTED; }

    shared_data_sys_->measure_value.current_time = shared_data_sys_->index;
    return KS_OK;
}

#define WIN32_LEAN_AND_MEAN
#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)

BOOL WINAPI DllMain([[maybe_unused]] HINSTANCE h_inst_dll,[[maybe_unused]]  DWORD reason, [[maybe_unused]]  LPVOID p_reserved) { return TRUE; }
